/* 使用组合式api ，提取的通用crud和from组件的封装hook */
import {
  ref,
  reactive,
  watch,
  watchEffect,
  getCurrentInstance,
  inject
} from "@vue/composition-api"
import objectMerge from '@/utils/objectMerge'
import axios from '@/utils/request'


/**
 *分页相关功能的封装
 *
 * @export hook 
 * @param {function} changeCallback page 的change被用户触发后的回调，一般传入刷新函数刷新crud
 * @returns {object} {page:{size,currentPage,total,offset},pageChange}
 */
export function usePage(changeCallback) {

  const page = reactive({
    size: 20,
    currentPage: 1,
    total: 0,
    offset: 0,
  })

  const pageChange = (data) => {
    page.currentPage = data.currentPage
    page.size = data.size
    page.offset = data.offset
    changeCallback && changeCallback()
  }
  return {
    page,
    pageChange,
  }
}


/**
 *crud 的常量及选项配置等封装
 *
 * @export hook
 * @returns {object} {crud,loading,data,option}
 */
export function useConst(props, {
  root
}, reduceHeight = 280) {
  const crud = ref(null)

  const loading = ref(false)
  const data = reactive({
    rows: [],
    count: 0,
  })

  const globalConfig = inject('globalConfig')

  /* 定义通用的默认的选项 crud的 */
  const option = reactive({
    table: {
      border: false,
      height: 0,
      stripe:true,
      align: "center",
      rowMenuColumn: {
        slot: false,
        type: "dropdown",
        width: "120px",
      },
      indexColumn: {
        display: true,
      },
      selectionColumn: {
        display: true,
      },
      column: [{
        label: "列1",
        prop: "col1"
      }, ]
    },
    search: {
      hideErrorMsg: true,
      size: globalConfig.elsize,
      menu: {
        align: 'left',
        span: 5,
        submitBtn: {
          text: '查询',
          icon: "el-icon-search",
          size: globalConfig.elsize,
        },
        resetBtn: {
          size: globalConfig.elsize,
        }
      },
      items: []
    },
    form: {
      size: globalConfig.elsize,
      labelWidth:"98px",
      menu: {
        submitBtn: {
          size: globalConfig.elsize,
        },
        resetBtn: {
          size: globalConfig.elsize,
        }
      },
    },
    headerMenu: {},
    footerMenu: {},
  })

  /* watch 全局的plugin提供的窗口宽高 动态修改crud table的高度*/
  // watch(window.hei,(val)=> {
  //         option.table.height = val - height
  // })

  watchEffect(() => {
    option.table.height = window.hei.value - reduceHeight
  })

  return {
    crud,
    loading,
    data,
    option,
  }
}


/**
 *搜索功能封装hook
 *
 * @export hook
 * @param {reactive} page reactive page args
 * @param {function} formDataTransFn 接收搜索表单的值并转换成condition返回
 * @param {function} cb 搜索提交，page change之后，条件给到condition之后执行，此处就可以刷新页面，从而实现搜索。
 * @returns {object} {condition<ref>,searchSubmit,searchChange}
 */
export function useSearch(page, formDataTransFn, cb) {
  const condition = ref({})
  const searchSubmit = (data, loading) => {
    condition.value = {};
    let condis = formDataTransFn && formDataTransFn(data)
    condis = condis ? condis : {}
    condition.value = condis;
    page.currentPage = 1;
    page.offset = 0;
    // 如果cb没有返回，则会报错，cb必须返回promise
    cb && cb().then(res => {
      loading && loading()
    })
  }
  const searchChange = (data) => {
    // console.log(data);
    searchSubmit(data)
  }
  const searchReset = () => {
    if (condition.value.length === 0) return
    condition.value = []
    cb && cb()
  }
  return {
    condition,
    searchSubmit,
    searchChange,
    searchReset,
  }
}


/**
 *crud 表格的通用权限处理，组件上只需绑定即可。
 *
 * @export
 */
export function useCrudCommonPermission(that) {

  // console.log(that.$route);
  // console.log( that.$store.state.permission.common_perm_list);

  const crudPermission = ref({})
  if (that.$store.getters.user_name === "admin") {
    // 管理员默认有所有权限
    crudPermission.value = [1, 2, 3, 4, 5, 6, 7, 8, 9]
  } else {
    crudPermission.value = that.$store.state.permission.common_perm_list[that.$route.meta.menu_id] || [];
  }
  return {
    crudPermission,
  }
}


/**
 *
 *new 封装一个通用的新的crud hook，crud组件使用时直接这一个引入就ok。以后可替换旧的crud内的散封装。
 *
 * @export
 * @param {*} _option crud需要的参数选项。{crudOption,getConfig():{},searchFormToCondition():[],reduceHeight:280}
 * @param {*} props 可选接收setup的props
 * @param {*} ctx 可选接收setup的ctx
 * @param {*} that 可选接收当前实例
 * @return {*} crud的属性和事件。
 */
export default function useCrud(_option, props, ctx, _that) {
  const that = _that || getCurrentInstance();
  // console.log(that);
  const option = {
    crudOption: {},
    getConfig: () => {
      return {}
    },
    // 与getConfig互斥，可直接传入请求的axios
    getMethod: null,
    searchFormToCondition() {
      return []
    },
    reduceHeight: 280
  }

  Object.assign(option, _option);

  // console.log(option.searchFormToCondition);

  const getList = (page, condition) => {
    consts.loading.value = true;
    if (option.getMethod) {
      return option.getMethod(page, condition).then(res => {
        that.$emit("get-list", res);
        // console.log(res);
        setTimeout(() => {
          consts.loading.value = false;
        }, 200);
        consts.data.rows = res.rows;
        consts.data.count = res.count;
        pages.page.total = res.count;
        return res;
      })
    }
    // that.$emit('abc',page)
    const config = option.getConfig(page, condition);
    if (!config.url) return;
    return axios(config).then(res => {
      // console.log(res);
      that.$emit("get-list", res);
      setTimeout(() => {
        consts.loading.value = false;
      }, 200);
      consts.data.rows = res.rows;
      consts.data.count = res.count;
      pages.page.total = res.count;
      return res;
    })

  }
  const refresh = () => {
    return getList(pages.page, searchs.condition.value)
  }
  const pages = usePage(refresh)
  const searchs = useSearch(pages.page, option.searchFormToCondition, refresh)
  const consts = useConst(null, {
    root: {}
  }, option.reduceHeight);
  objectMerge(option.crudOption, consts.option, true) //传入的option合并进入

  const selectedList = ref([])
  const selectionChange = (rows) => {
    selectedList.value = rows;
  }

  /** 行双击，默认打开编辑窗口 */
  const onRowDblclick = (row, col, e) => {
    consts.crud.value.openEditRow()
  }

  const perms = useCrudCommonPermission(that)


  return {
    refresh,
    ...pages,
    ...searchs,
    ...consts,
    selectedList,
    selectionChange,
    onRowDblclick,
    ...perms,
  }
}
